package com.seek.core;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.math.BigInteger;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author 涂小炼
 * 
 * @param <T>
 */

@Transactional
public class BaseDaoImpl<T extends Serializable> implements BaseDao<T> {
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Resource
	private SessionFactory sessionFactory;

	private Class<T> persistentClass;

	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	/**
	 * 根据某个某个属性值得到相应实体个数
	 */
	public int countByProperty(String property, Object value) {
		return ((Number) (createCriteria(Restrictions.eq(property, value))
				.setProjection(Projections.rowCount()).uniqueResult()))
				.intValue();
	}

	/**
	 * 删除某个实体
	 */
	public T delete(T entity) {
		getSession().delete(entity);
		return entity;
	}

	/**
	 * 根据实体ID删除某个实体
	 */
	public T deleteById(Serializable id) {
		T entity = load(id);
		getSession().delete(entity);
		return entity;
	}

	/**
	 * 删除集合中的全部实体
	 */
	public void deleteAllByIds(Serializable[] ids) {
		for (Serializable id : ids) {
			T entity = load(id);
			getSession().delete(entity);
		}
	}	
	
	/**
	 * 返回某种实体的集合
	 */
	public List<T> findAll() {
		return findByCriteria();
	}

	/**
	 * 通过动态查询条件进行查询
	 * 
	 * @param criterion
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected List<T> findByCriteria(Criterion... criterion) {
		return createCriteria(criterion).list();
	}

	/**
	 * 根据某个某个属性值的到实体List
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String property, Object value) {
		return createCriteria(Restrictions.eq(property, value)).list();
	}

	/**
	 * 根据某个某个属性值的到某个实体
	 */
	@SuppressWarnings("unchecked")
	public T findUniqueByProperty(String property, Object value) {
		try {
			return (T) createCriteria(Restrictions.eq(property, value))
					.uniqueResult();
		} catch (RuntimeException ex) {
			logger.error("系统异常",ex);
			throw ex;
		}
	}
	
	/**
	 * 根据hql语句得到某个实体
	 */
	@SuppressWarnings("unchecked")
	public T findUniqueByHql(String hql,Object...values) {
		return (T)createQuery(hql, values).uniqueResult();
	}

	/**
	 * 根据ID得到某个实体
	 */
	@SuppressWarnings("unchecked")
	public T get(Serializable id) {
		return (T) getSession().get(getPersistentClass(), id);
	}

	/**
	 * 添加实体
	 */
	public T insert(T entity) {
		getSession().persist(entity);
		return entity;
	}

	/**
	 * 根据ID得到某个实体
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public T load(Serializable id, boolean lock) {
		T entity = null;
		if (lock) {
			entity = (T) getSession().load(getPersistentClass(), id,
					LockMode.UPGRADE);
		} else {
			entity = (T) getSession().load(getPersistentClass(), id);
		}
		return entity;
	}

	/**
	 * 根据ID得到某个实体
	 */
	public T load(Serializable id) {
		return load(id, false);
	}

	/**
	 * 更新某个实体
	 */
	public T update(T entity) {
		getSession().merge(entity);
		return entity;
	}

	/**
	 * 创建检索条件
	 * @param criterion
	 * @return
	 */
	protected Criteria createCriteria(Criterion... criterions) {
		Criteria criteria = getSession().createCriteria(getPersistentClass());
		for (Criterion c : criterions) {
			criteria.add(c);
		}
		return criteria;
	}

	/**
	 * 更新或增加一个实体
	 */
	public T saveOrUpdate(T entity) {
		getSession().saveOrUpdate(entity);
		return entity;
	}

	/**
	 * 
	 */
	public void refresh(T entity) {
		getSession().refresh(entity);
	}

	/**
	 * 更新或增加集合中的全部实体
	 */
	public void saveOrUpdateAll(List<T> list) {
		for (T t : list) {
			getSession().saveOrUpdate(t);
		}
	}

	/**
	 * 按HQL查询对象列表.
	 * 
	 * @param hql
	 *            hql语句
	 * @param values
	 *            数量可变的参数
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByHql(String hql, Object... values) {
		return createQuery(hql, values).list();
	}

	/**
	 * 根据查询函数与参数列表创建Query对象,后续可进行更多处理,辅助函数.
	 */
	public Query createQuery(String queryString, Object... values) {
		Query queryObject = getSession().createQuery(queryString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i, values[i]);
			}
		}
		return queryObject;
	}

	/**
	 * 创建SQLQuery对象
	 * @param queryString
	 * @param values
	 * @return
	 */
	protected SQLQuery createSQLQuery(String queryString, Object... values) {
		SQLQuery queryObject = getSession().createSQLQuery(queryString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i, values[i]);
			}
		}
		return queryObject;
	}

	/**
	 * 根据sql语句查询集合
	 */
	@SuppressWarnings("unchecked")
	public List<T> findBySql(String sql, Object... values) {
		return createSQLQuery(sql, values).addEntity(getPersistentClass()).list();
	}
	public List findMapBySql(String sql, Object... values) {
		return createSQLQuery(sql, values).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
	}
	
	public Object findUniqueMapBySql(String sql,Object... values) {
		return createSQLQuery(sql, values).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).uniqueResult();
	}

	/**
	 * 使用 hql 语句进行操作
	 * 
	 * @param hql
	 *            HSQL 查询语句
	 * @param offset
	 *            开始取数据的下标
	 * @param length
	 *            读取数据记录数
	 @param values
	 *            数量可变的参数
	 * @return List 结果集
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByHql(String hql,int offset,int length, Object... values) {
		return createQuery(hql, values).setFirstResult(offset).setMaxResults(length).list();
	}
	
	/**
	 * 使用 hql 语句进行操作
	 * 
	 * @param hql
	 *            HSQL 查询语句（使用回调函数访问外部变量，必须是final的）
	 * @param offset
	 *            开始取数据的下标
	 * @param length
	 *            读取数据记录数
	 * @return List 结果集
	 */
	@SuppressWarnings("unchecked")
	public List<T> getListForPage(final String hql, final int offset,
			final int length) {
		return this.getSession().createQuery(hql).setFirstResult(offset)
				.setMaxResults(length).list();
	}
	
	/**
	 * 使用 sql 语句进行操作
	 * 
	 * @param sql
	 *            SQL 查询语句（使用回调函数访问外部变量，必须是final的）
	 * @param offset
	 *            开始取数据的下标
	 * @param length
	 *            读取数据记录数
	 * @return List 结果集
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<T> getListForPageBySql(final String sql, final int offset,
			final int length,Class c) {
		return this.getSession().createSQLQuery(sql).addEntity(c).setFirstResult(offset)
				.setMaxResults(length).list();
	}
	/**
	 * 分页查询，返回List<Map<String,String>>
	 */
	public List getListMapForPageBySql(final String sql, final int offset,
			final int length) {
		return this.getSession().createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).setFirstResult(offset)
				.setMaxResults(length).list();
	}
	
	/**
	 * 
	 * getAllRowCount:查询所有记录数
	 * 
	 * @param hql hql语句
	 * @return int 返回总记录数
	 * 
	 * 
	 */
	public int getAllRowCount(String hql) {
		return ((Long)this.getSession().createQuery(hql).list().get(0)).intValue();
	}
	
	/**
	 * 
	 * getAllRowCountBySql:查询所有记录数
	 * 
	 * @param sql sql语句
	 * @return int 返回总记录数
	 * 
	 * 
	 */
	public int getAllRowCountBySql(String sql) {
		return ((BigInteger)this.getSession().createSQLQuery(sql).list().get(0)).intValue();
	}
	
	/**
	 * 
	 * getAllRowCount:查询所有记录数
	 * 
	 * @param hql hql语句
	 * @param values
	 *            数量可变的参数
	 * @return int 返回总记录数
	 * 
	 * 
	 */
	public int getAllRowCount(String hql,Object...values) {
		List<?> list = createQuery(hql, values).list();
		if (list.size() > 0) {
			return ((Long) list.get(0)).intValue();
		} else
			return 0;
	}
	
	/**
	 * 根据Class、ID得到某个实体
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public T get(Class c, Serializable id) {
		return (T) getSession().get(c, id);
	}
	
	/**
	 * 
	 * removeByOtherId:(通过hql语句删除记录)
	 *
	 * @param  @param hql
	 * @param  @param values
	 * @param  @return 
	 * @return int
	 */
	public int removeByOtherId(String hql, Object... values) {
		Query q = createQuery(hql, values);
	    return q.executeUpdate() ;
	}
	
	/**
	 * 根据sql语句查询集合
	 */
	@SuppressWarnings("rawtypes")
	public List findBySql(String sql) {
		return createSQLQuery(sql).list();
	}
	
	public void executeUpdateSql(String sql,Object... values) throws Exception{
		this.createSQLQuery(sql, values).executeUpdate();
	}
	
	public int executeUpdateSqlWithRetun(String sql,Object... values) throws Exception{
		return this.createSQLQuery(sql, values).executeUpdate();
	}
}
